/*
 * @(#)XMLDataModelResult.java $version 2010. 8. 11
 *
 * Copyright 2007-2010 NHN Corp. All rights Reserved. 
 * NHN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package com.nhncorp.usf.core.result;

import java.util.List;
import java.util.Map;

import com.nhncorp.usf.core.config.AttributeInfo;
import com.nhncorp.usf.core.config.AttributeInfo.ATTRIBUTE_NAME;
import com.nhncorp.usf.core.config.runtime.ResultPageInfo;

/**
 * 디버깅용으로 RAW데이터를 보여주는 Result {@link Result}.
 *
 * @author Web Platform Development Team
 */
@SuppressWarnings("serial")
public class XMLDataModelResult extends AbstractDataModelResult {
    private static String checkDataModel;

    static {
        checkDataModel = AttributeInfo.getInstance().getAttribute(ATTRIBUTE_NAME.checkDataModel);
    }

    /**
     * 전달된 {@link DataMap} 정보를 {@link ResultPageInfo} 에 적용하여 결과 페이지 내보냄.
     * 
     * @param resultPage the ResultPageInfo
     * @param dataMap the data map
     * @throws Exception the Exception
     */
    public void execute(ResultPageInfo resultPage, Map<String, Object> dataMap) throws Exception {
    	Map<String, Object> usfEmbeddedData = generateResultData("text/xml; charset=", dataMap);
        StringBuffer sb = new StringBuffer();
        sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
        sb.append("<xml-data>\n");
        sb.append("<bo-result>\n");
        sb.append(generateMapTable(dataMap, "return-id", "CONTENT"));
        sb.append("</bo-result>\n");
        sb.append("<input-params>\n");
        sb.append(generateMap2Table(usfEmbeddedData, "default"));
        sb.append("</input-params>\n");
        sb.append("</xml-data>");
        out.println(sb.toString());
        out.flush();
    }

    /**
     * Generate map table.
     *
     * @param dataMap the data map
     * @return the string buffer
     */
    private StringBuffer generateMapTable(Map<String, Object> dataMap) {
        StringBuffer sb = new StringBuffer();
        sb.append(generateMapTable(dataMap, "key", "value"));
        return sb;
    }

    /**
     * Generate map table.
     *
     * @param dataMap     the data map
     * @param keyString   the key string
     * @param valueString the value string
     * @return the string buffer
     */
    @SuppressWarnings("unchecked")
	private StringBuffer generateMapTable(Map<String, Object> dataMap, String keyString, String valueString) {
        StringBuffer sb = new StringBuffer();

        for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
            sb.append("<" + entry.getKey());
            Object obj = entry.getValue();

            if (obj instanceof Map) {
                sb.append(" type = \"" + getType(obj) + "\" >\n");
                sb.append(generateMapTable((Map<String, Object>)obj));
            } else if (obj instanceof List) {
                sb.append(" type = \"" + getType(obj) + "\" >\n");
                sb.append(generateListTable((List)obj));
            } else {
                sb.append(" type = \"" + getType(obj) + "\" >");
                sb.append("<![CDATA[" + obj + "]]>");
            }

            sb.append("</" + entry.getKey() + ">\n");
        }

        return sb;
    }

    /**
     * Generate list table.
     *
     * @param list the list
     * @return the string buffer
     */
    @SuppressWarnings("unchecked")
	private StringBuffer generateListTable(List list) {
        StringBuffer sb = new StringBuffer();

        for (Object obj : list) {
            if (obj instanceof Map) {
                sb.append("<item type=\"map\">\n");
                sb.append(generateMapTable((Map<String, Object>)obj, "key", "value"));
                sb.append("</item>\n");
            } else if (obj instanceof List) {
                sb.append("<item type=\"list\">\n");
                sb.append(generateListTable((List)obj));
                sb.append("</item>\n");
            } else {
                sb.append("<item type=\"" + getType(obj) + "\">" + "<![CDATA[" + obj + "]]>" + "</item>\n");
            }
        }

        return sb;
    }

    /**
     * Generate map2 table.
     *
     * @param dataMap the data map
     * @param option  the option
     * @return the string buffer
     */
    private StringBuffer generateMap2Table(Map<String, Object> dataMap, Object option) {
        StringBuffer sb = new StringBuffer();
        sb.append(generateMap2Table(dataMap, "key", "value", option));
        return sb;
    }

    /**
     * Generate map2 table.
     *
     * @param dataMap     the data map
     * @param keyString   the key string
     * @param valueString the value string
     * @param option      the option
     * @return the string buffer
     */
    @SuppressWarnings("unchecked")
	private StringBuffer generateMap2Table(Map<String, Object> dataMap, String keyString, String valueString,
                                           Object option) {
        StringBuffer sb = new StringBuffer();
        
        for (Map.Entry<String, Object> entry : dataMap.entrySet()) {

            if (entry.getKey().equals(checkDataModel)) {
                continue;
            }

            sb.append("<" + entry.getKey());
            Object obj = entry.getValue();

            if (obj instanceof Map) {
                sb.append(" type = \"" + getType(obj) + "\" >\n");
                sb.append(generateMap2Table((Map<String, Object>)obj, null));
            } else if (obj instanceof List) {
                sb.append(" type = \"" + getType(obj) + "\" >\n");
                sb.append(generateList2Table((List)obj));
            } else {
                sb.append(" type = \"" + getType(obj) + "\" >");
                sb.append("<![CDATA[" + obj + "]]>");
            }

            sb.append("</" + entry.getKey() + ">\n");
        }

        return sb;
    }

    /**
     * Generate list2 table.
     *
     * @param list the list
     * @return the string buffer
     */
    @SuppressWarnings("unchecked")
	private StringBuffer generateList2Table(List list) {
        StringBuffer sb = new StringBuffer();

        for (Object obj : list) {
            if (obj instanceof Map) {
                sb.append("<item type=\"map\">\n");
                sb.append(generateMap2Table((Map<String, Object>)obj, "key", "value", null));
                sb.append("</item>\n");
            } else if (obj instanceof List) {
                sb.append("<item type=\"list\">\n");
                sb.append(generateList2Table((List)obj));
                sb.append("</item>\n");
            } else {
                sb.append("<item type=\"" + getType(obj) + "\">" + "<![CDATA[" + obj + "]]>" + "</item>\n");
            }
        }

        return sb;
    }

    /**
     * Gets the type.
     *
     * @param obj the obj
     * @return the type
     */
    private String getType(Object obj) {
        if (obj == null) {
            return "NULL";
        }

        return obj.getClass().getSimpleName();
    }
}